<?php
/**
 * 
 * @author 曹勇
 * @dependon Field
 */
class Form implements Iterator
{
	protected $validator;
	protected $fields = [];
	protected $valid_csrf = true;
	protected $csrf_name = '';//开启csrf验证时请配置此项
	protected $method = 'POST';
	
	public function __construct()
	{
		if(false === $this->validCsrf())
		{
			throw new Exception('csrf token error');
		}
		$this->init();
	}
	
	public function init()
	{		
		foreach ($this as $field)
		{
			$field->setValue($this->_input($field->getName()));
		}
	}
	
	public function validCsrf()
	{
		if (!$this->valid_csrf)
			return true;
		return isset($_SESSION['csrf_name']) && $_SESSION[$this->csrf_name] == $this->_input($this->csrf_name);
	}
	
	protected function _input($name)
	{
		if ('POST' == $this->method)
			$method = &$_POST;
		else 
			$method = &$_GET;
		
		return isset($method[$name]) ? $method[$name] : null;
	}
	
	public function setField($name,Field $field)
	{
		$this->fields[$name] = $field;
		return $this;
	}
	
	public function newField($name,$type,$value = null)
	{
		$field = $this->buildField($name, $type);
		if (null !== $field)
			$field->setValue($value);
		$this->setField($name, $field);
		return $this;
	}
	
	public function getField($name)
	{
		if (!isset($this->fields[$name]))
			throw new Exception('Field '.$name.' not exists');
		
		return $this->fields[$name];
	}
	
	public function getValue($name)
	{
		return $this->getField($name)->getValue();
	}
	
	public function setValue($name,$value)
	{
		$this->getField($name)->setValue($value);
		return $this;
	}
	
	public function getValues()
	{
		$values = [];
		foreach ($this as $name => $field)
		{
			$values[$name] = $field->getValue();
		}
		return $values;
	}
	
	public function buildField($name,$type)
	{
		return new Field($name, $type);
	}
	
	public function current()
	{
		return current($this->fields);
	}
	
	public function next()
	{
		return next($this->fields);
	}
	
	public function rewind()
	{
		reset($this->fields);
	}
	
	public function key()
	{
		return key($this->fields);
	}
	
	public function valid()
	{
		return $this->current() !== false;
	}
}